﻿using System.Collections.Generic;
using System.Linq;
using JetBrains.ReSharper.Psi.Resolve;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.ReSharper.Psi.Xaml;
using JetBrains.ReSharper.Psi.Xaml.Tree;
using JetBrains.ReSharper.Psi.Xml.Tree;
using JetBrains.Util;

namespace GammaJul.ReSharper.GammaXaml.Psi.Xaml {
	
	/// <summary>
	/// Provides references on a XAML field to the implicitly Caliburn.Micro-bound view model method or property.
	/// </summary>
	internal class CaliburnXamlReferenceProvider : IReferenceFactory {

		public IReference[] GetReferences(ITreeNode element, IReference[] oldReferences) {
			if (!Equals(element.Language, XamlLanguage.Instance))
				return EmptyArray<IReference>.Instance;
			
			var declNameAttr = element as IXNameAttribute;
			if (declNameAttr == null)
				return EmptyArray<IReference>.Instance;

			if (oldReferences != null && (oldReferences.Length == 1 || oldReferences.Length == 2) && oldReferences.All(r => r is CaliburnBoundXamlReference))
				return oldReferences;

			CaliburnBoundXamlReference methodOrPropertyReference = CaliburnBoundXamlReference.FromDeclarationNameAttribute(declNameAttr);
			CaliburnGuardBoundXamlReference guardReference = CaliburnGuardBoundXamlReference.FromDeclarationNameAttribute(declNameAttr, methodOrPropertyReference);
			
			return new IReference[] {
				methodOrPropertyReference, // method (eg: Save)
				guardReference // guard (eg: CanSave)
			};
		}

		public bool HasReference(ITreeNode element, ICollection<string> names) {
			var valueToken = element as IXmlValueToken;
			return valueToken != null && names.Contains(valueToken.UnquotedValue);
		}

	}

}